/*
 * Copyright (c) 2025 HiEasyX
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * \file hex_button.cpp
 * \brief The button for HiEasyX
 */

#include <include/hex.h>
#include <include/hex_button.h>

namespace HX {
HXRect CalButtonRect(ButtonProfile &Profile, HXPoint &Position, const HXRect &fontRect) {
	constexpr HXGInt contentGap = 4;
	auto buttonRectangle = HXRect{Position.X, Position.Y,
								  Position.X + fontRect.Right + contentGap,
								  Position.Y + contentGap + fontRect.Bottom};
	if (Profile.Size.X > 0) {
		buttonRectangle.Right = buttonRectangle.Left + Profile.Size.X;
	}
	if (Profile.Size.Y > 0) {
		buttonRectangle.Bottom = buttonRectangle.Top + Profile.Size.Y;
	}

	return buttonRectangle;
}
bool Button(const HXString &Title, ButtonProfile &Profile) {
	if (RoughVisibility()) {
		return false;
	}

	auto &context = GetContext();
	auto &theme   = GetTheme();

	auto position = CurrentLayoutPosition();

	auto painter = CurrentPainter();

	constexpr HXGInt contentGap = 4;

	const auto fontRect = painter->MeasureText(Title, HXFont{}, 18);

	auto buttonRectangle = CalButtonRect(Profile, position, fontRect);

	const auto width  = buttonRectangle.CalWidth();
	const auto height = buttonRectangle.CalHeight();

	if (AccVisibility({width, height})) {
		return false;
	}
	if (!CurrentVisibility({ width, height })) {
		if (NeedLayoutCal()) {
			LayoutNextControl({ width, height });
		}

		return false;
	}

	bool pressed = false;

	// Process the presse or hover
	for (auto &Message : context.MessageQuery) {
		auto mouse = ClipCoord({Message.MouseX, Message.MouseY});
		if (Message.Processed) {
			continue;
		}
		if (Message.MouseAction) {
			if (buttonRectangle.PointInside(mouse)) {
				Profile.OnHover = true;
				if (Message.MouseLeftPressed) {
					Message.Processed = true;

					Profile.OnHold = true;
				}
				if (Message.MouseLeftRelease) {
					Profile.OnHold = false;

					pressed = true;
				}
			} else if (Profile.OnHover) {
				Profile.OnHover = false;
				Profile.OnHold  = false;
			}
		}
	}

	painter->Begin();

	if (Profile.OnHold) {
		painter->DrawFilledRectangle(buttonRectangle, theme.ButtonPressedBorder,
		                             theme.ButtonPressedBackground);
		painter->DrawText(Title, HXFont{},
		                  {position.X + width / 2 - fontRect.Right / 2,
		                   position.Y + height / 2 - fontRect.Bottom / 2,},
		                  theme.ButtonPressedText, 18);
	} else if (Profile.OnHover) {
		painter->DrawFilledRectangle(buttonRectangle, theme.ButtonOnHoverBorder,
		                             theme.ButtonOnHoverBackground);
		painter->DrawText(Title, HXFont{},
						  {position.X + width / 2 - fontRect.Right / 2,
						   position.Y + height / 2 - fontRect.Bottom / 2,},
						  theme.ButtonOnHoverText, 18);
	} else {
		painter->
			DrawFilledRectangle(buttonRectangle, theme.ButtonBorder, theme.ButtonBackground);
		painter->DrawText(Title, HXFont{},
						  {position.X + width / 2 - fontRect.Right / 2,
						   position.Y + height / 2 - fontRect.Bottom / 2,},
						  theme.ButtonText, 18);
	}

	painter->End();

	Profile.OnPressed = pressed;

	LayoutNextControl({width, height});

	return pressed;
}
}
